
using namespace std;

int main()
{
    // delete p; // p 必须指向一个动态分配的对象或是一个空指针

    int i, *pi1 = &i, *pi2 = nullptr;
    double *pd = new double(33), *pd2 = pd;
    // delete i;       // 错误：i 不是一个指针
    delete pi1;     // 未定义：pi1 指向一个局部变量
    delete pd;      // 正确
    delete pd2;     // 未定义：pd2 指向的内存已经被释放了
    delete pi2;     // 正确：释放一个空指针总是没有错误的

    const int *pci = new const int(1024);
    delete pci; // 正确：释放一个 const 对象

    int *p(new int(42));    // p 指向动态内存
    auto q = p;             // p 和 q 指向相同的内存
    delete p;               // p 和 q 均变为无效
    p = nullptr;            // 指出 p 不再绑定到任何对象
}

template <typename T> class Foo {
    public:
        Foo(T arg): data(arg) {}
    private:
        T data;
};

// factory 返回一个指针，指向一个动态分配的对象
template <typename T> Foo<T>* factory(T arg)
{
    // 视情况处理 arg
    return new Foo<T>(arg); // 调用者负责释放此内存
}

// template <typename T> void use_factory(T arg)
// {
//     Foo<T> *p = factory(arg);
//     // 使用 p 但不 delete 它
// } // p 离开了它的作用域，但它所指向的内存没有被释放！

template <typename T> void use_factory(T arg)
{
    Foo<T> *p = factory(arg);
    // 使用 p
    delete p; // 现在记得释放内存，我们已经不需要它了
}

template <typename T> Foo<T>* use_factory(T arg)
{
    Foo<T> *p = factory(arg);
    // 使用 p
    return p; // 调用者必须释放内存
}